feat(chat): show specific turn failure reasons in the transcript - #1697
Conversation
Surface the stable privacy-safe failureCode on failed turns so the UI can name the failure type instead of one generic agent error. Co-Authored-By: David Cramer <david@sentry.io>
Use one report-schema failure code type across the API and transcript UI, and keep failure labels plain. Co-Authored-By: David Cramer <david@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dashboard visual evidenceMode: path-selected Triggered by:
Component gallery index · desktopConversations · desktopConversations · mobileConversation detail · desktopConversation detail · mobileConversation detail · focused composer · mobileFull-page screenshots from the mock dashboard. Not a pixel-diff gate. |
There was a problem hiding this comment.
Answering against the JUNIOR-8T / provider-network spike concerns from the Slack thread:
No — this does not cover those concerns.
This PR is useful on its own axis: it replaces the coarse failureKind (agent | delivery) with stable failureCodes and surfaces them in the transcript, export, and search. That helps the conversation UI name which lifecycle class failed.
What it does not address from that incident:
- Upstream stream failure after gateway HTTP 200 — the failing path was
stopReason=erroronopenai/gpt-5.6-solvia AI Gateway, with 3 provider retries, not a dashboard labeling gap. - Sentry diagnosis of provider errors —
agent.turn.provider_errorstill collapses toAI provider error: networkand intentionally omits the raw providererrorMessage, so the next spike is still hard to attribute (gateway/model stream vs junior). - Finer failure class inside model execution —
model_execution_failedis still one bucket; it does not distinguish network/stream, capacity, auth, invalid_response, etc.
Ship this if you want better transcript failure UX. For the JUNIOR-8T concerns, the missing piece is still safer provider-error telemetry (and/or fixing the stream path), not dashboard copy.
Store a privacy-safe failureReason on failed turns and render the specific model/provider or execution reason in the transcript. Co-Authored-By: David Cramer <david@sentry.io>
Share turn failure schemas from history, drop developer jargon from UI copy, and keep provider error kinds owned by the provider boundary. Co-Authored-By: David Cramer <david@sentry.io>
CI typecheck failed because nested failure switches did not prove a return on every path.
) JUNIOR-8T showed `ProviderError: AI provider error: network` after AI Gateway returned HTTP 200 and the model stream failed. Junior already classified and retried correctly, but terminal Sentry events and retry logs dropped the provider cause text. That left the spike looking like a generic network outage with no way to tell stream-incomplete wording from a true transport failure. #1697 improved transcript failure codes and `app.ai.failure_reason`. That names the lifecycle class. It still does not keep a safe provider cause string on the provider-error path. This keeps a short, redacted provider summary on the paths that matter: - `app.ai.provider_error.summary` on terminal provider-error captures - the same fields on `agent.turn.provider.retrying`, plus `app.ai.provider_error.retry_attempt` - `gen_ai.chat` span attributes/status when `stopReason=error` Gateway JSON bodies are stripped so telemetry stays free of raw provider payloads. User-facing copy is unchanged. This does not stop upstream stream failures. It makes the next JUNIOR-8T-style spike attributable, including the one-conversation prompt/history hypothesis. Evidence: https://sentry.sentry.io/issues/7692564933/ <!-- junior-request-attribution:start --> Requested by **David Cramer**. <!-- junior-request-attribution:end --> <!-- junior-session-footer:start --> <!-- junior-conversation-id:slack%3AC0B595QDZLL%3A1787705529.828609 --> -- [View Junior Session](https://junior-prod.sentry.dev/conversations/slack%3AC0B595QDZLL%3A1787705529.828609) [[Sentry]](https://sentry.sentry.io/explore/conversations/slack%3AC0B595QDZLL%3A1787705529.828609/?project=4510944073809921) <!-- junior-session-footer:end --> --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: David Cramer <david@sentry.io>






Failed turns in the conversation UI only said the model stopped early. That hid the real failure class and the specific reason.
This change keeps the stable lifecycle
failureCodeand adds an optional fixedfailureReasonon failed turns. Model service failures store the provider kind (network,rate_limit,capacity,auth, and so on). Empty or tool-stopped runs store a fixed run class.The transcript, markdown export, and search render that reason when present. Example titles:
Raw exception text still stays out of the report API.
Requested by David Cramer.
--
View Junior Session [Sentry]